package com.ssy.lingxi.system.service.impl;

import com.ssy.lingxi.common.constant.CommonConstant;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.system.common.SystemConstant;
import com.ssy.lingxi.system.dao.MiddlegroundMenuRepository;
import com.ssy.lingxi.system.dao.MiddlegroundMenuRoleRepository;
import com.ssy.lingxi.system.dto.request.*;
import com.ssy.lingxi.system.dto.response.MiddlegroundMenuResponse;
import com.ssy.lingxi.system.dto.response.MiddlegroundUserLoginResponse;
import com.ssy.lingxi.system.dto.response.RoleLoginResponse;
import com.ssy.lingxi.system.entity.MiddlegroundMenu;
import com.ssy.lingxi.system.entity.MiddlegroundMenuRole;
import com.ssy.lingxi.system.service.MiddlegroundMenuService;
import com.ssy.lingxi.system.utils.ObjectUtil;
import com.ssy.lingxi.system.utils.UserDetailsUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MiddlegroundMenuServiceImpl implements MiddlegroundMenuService {
    @Autowired
    UserDetailsUtil userDetailsUtil;
    @Autowired
    MiddlegroundMenuRepository middlegroundMenuRepository;
    @Autowired
    MiddlegroundMenuRoleRepository roleMenuRepository;

    @Override
    public Wrapper<List<MiddlegroundMenuResponse>> menuList() {
        List<MiddlegroundMenu> all = middlegroundMenuRepository.findAllByTypeEquals(SystemConstant.MuenType.MEUN);
        List<MiddlegroundMenuResponse> middlegroundMenuResponses = new ArrayList<>();
        all.forEach(menu -> {
            MiddlegroundMenuResponse middlegroundMenuResponse = new MiddlegroundMenuResponse();
            BeanUtils.copyProperties(menu, middlegroundMenuResponse);
            middlegroundMenuResponse.setKey(menu.getId());
            middlegroundMenuResponse.setTitle(menu.getMenuName());
            middlegroundMenuResponses.add(middlegroundMenuResponse);
        });
        //去重 排序
        List<MiddlegroundMenuResponse> menuResponses = middlegroundMenuResponses.stream().filter(ObjectUtil.distinctByKey(l -> l.getKey())).collect(Collectors.toList()).stream().sorted(Comparator.comparing(MiddlegroundMenuResponse::getSort)).collect(Collectors.toList());
        Map<Long, List<MiddlegroundMenuResponse>> menuMap = menuResponses.stream().collect(Collectors.groupingBy(middlegroundMenu -> middlegroundMenu.getParentId()));
        //顶级菜单
        List<MiddlegroundMenuResponse> menus = menuMap.get(0L);
        if (null != menus && menus.size() > 0) {
            menus.forEach(menu -> {
                menuResponseList(menuMap, menu.getKey(), menu);
            });
        }
        return Wrapper.success(menus);
    }

    @Transactional
    @Override
    public Wrapper menuAdd(MiddlegroundMenuAddRequest request, HttpServletRequest httpServletRequest) {
        MiddlegroundUserLoginResponse loginUserDetails = userDetailsUtil.getLoginUserDetails(httpServletRequest);
        MiddlegroundMenu menu = new MiddlegroundMenu();
        if (null != loginUserDetails) {
            List<RoleLoginResponse> roles = loginUserDetails.getRoles();
            if (null != roles && !roles.isEmpty()) {
                menu.setCreateRole(roles.get(0).getName());
            }
        }
        menu.setCreateTime(System.currentTimeMillis());
        menu.setMenuDescribe(request.getMenuDescribe());
        menu.setMenuName(request.getMenuName());
        menu.setParentId(request.getParentId());
        menu.setPath(request.getUrl());
        menu.setType(SystemConstant.MuenType.MEUN);
        menu.setSort(request.getSort());
        menu.setState(CommonConstant.State.STATE_START);
        MiddlegroundMenu save = middlegroundMenuRepository.save(menu);
        List<MiddlegroundMenu> list = new ArrayList<>();
        if (null != request.getButtons() && request.getButtons().size() > 0) {
            List<ButtonAddRequest> buttons = request.getButtons();
            buttons.forEach(buttonAddRequest -> {
                MiddlegroundMenu middlegroundMenu = new MiddlegroundMenu();
                if (null != loginUserDetails) {
                    List<RoleLoginResponse> roles = loginUserDetails.getRoles();
                    if (null != roles && !roles.isEmpty()) {
                        menu.setCreateRole(roles.get(0).getName());
                    }
                }
                middlegroundMenu.setCreateTime(System.currentTimeMillis());
                middlegroundMenu.setMenuDescribe(buttonAddRequest.getButtonExplain());
                middlegroundMenu.setMenuName(buttonAddRequest.getButtonName());
                middlegroundMenu.setParentId(save.getId());
                middlegroundMenu.setPath(buttonAddRequest.getButtonUrl());
                middlegroundMenu.setType(SystemConstant.MuenType.BUTTON);
                middlegroundMenu.setState(CommonConstant.State.STATE_START);
                list.add(middlegroundMenu);
            });
            middlegroundMenuRepository.saveAll(list);
        }
        return Wrapper.success();
    }

    @Transactional
    @Override
    public Wrapper menuDelete(MiddlegroundMenuDeleteRequest request) {
        middlegroundMenuRepository.deleteById(request.getId());
        return Wrapper.success();
    }

    /**
     * 根据角色ID查询权限菜单列表
     *
     * @return
     * @author wrc
     * @date 2020/5/12
     */
    @Override
    public Wrapper<List<MiddlegroundMenuResponse>> menuListByRoleId(HttpServletRequest request) {
        MiddlegroundUserLoginResponse loginUserDetails = userDetailsUtil.getLoginUserDetails(request);
        List<MiddlegroundMenuResponse> menuResponseList = new ArrayList<>();
        loginUserDetails.getRoles().forEach(roleLoginResponse -> {
            MiddlegroundMenuRole roleMenu = new MiddlegroundMenuRole();
            roleMenu.setRoleId(roleLoginResponse.getId());
            Example<MiddlegroundMenuRole> example = Example.of(roleMenu);
            List<MiddlegroundMenuRole> menuRoles = roleMenuRepository.findAll(example);
            List<Long> ids = new ArrayList<>();
            menuRoles.forEach(roleAndMenu -> {
                ids.add(roleAndMenu.getMenuId());
            });
            List<MiddlegroundMenu> menuList = middlegroundMenuRepository.findAllById(ids);
            List<MiddlegroundMenuResponse> middlegroundMenuResponses = new ArrayList<>();
            menuList.forEach(menu -> {
                MiddlegroundMenuResponse middlegroundMenuResponse = new MiddlegroundMenuResponse();
                BeanUtils.copyProperties(menu, middlegroundMenuResponse);
                middlegroundMenuResponses.add(middlegroundMenuResponse);
            });
            menuResponseList.addAll(middlegroundMenuResponses);
        });
        //去重 排序
        List<MiddlegroundMenuResponse> menuResponses = menuResponseList.stream().filter(ObjectUtil.distinctByKey(l -> l.getKey())).collect(Collectors.toList()).stream().sorted(Comparator.comparing(MiddlegroundMenuResponse::getSort)).collect(Collectors.toList());
        Map<Long, List<MiddlegroundMenuResponse>> menuMap = menuResponses.stream().collect(Collectors.groupingBy(middlegroundMenu -> middlegroundMenu.getParentId()));
        List<MiddlegroundMenuResponse> menus = menuMap.get(0L);
        if (null != menus && menus.size() > 0) {
            menus.forEach(menu -> {
                menuResponseList(menuMap, menu.getKey(), menu);
            });
        }
        return Wrapper.success(menus);
    }

    /**
     * 递归查询菜单的下级菜单
     *
     * @author wrc
     * @date 2020/5/22
     */
    private void menuResponseList(Map<Long, List<MiddlegroundMenuResponse>> collect, Long id, MiddlegroundMenuResponse middlegroundMenuResponse) {
        List<MiddlegroundMenuResponse> middlegroundMenus = collect.get(id);
        if (null != middlegroundMenus && middlegroundMenus.size() > 0) {
            middlegroundMenus.forEach(middlegroundMenu -> {
                middlegroundMenuResponse.setChildren(middlegroundMenus);
                menuResponseList(collect, middlegroundMenu.getKey(), middlegroundMenu);
            });
        }
        return;
    }

    /**
     * 配置角色权限
     *
     * @author wrc
     * @date 2020/5/13
     */
    @Transactional
    @Override
    public Wrapper menuRoleBinding(MenuBindingRoleRequest request) {
        //先删除再添加
        MiddlegroundMenuRole rm = new MiddlegroundMenuRole();
        rm.setRoleId(request.getRoleId());
        roleMenuRepository.delete(rm);
        List<Long> menus = request.getMenus();
        List<MiddlegroundMenuRole> roleMenus = new ArrayList<>();
        menus.forEach(id -> {
            MiddlegroundMenuRole roleMenu = new MiddlegroundMenuRole();
            roleMenu.setRoleId(request.getRoleId());
            roleMenu.setMenuId(id);
            roleMenus.add(roleMenu);
        });
        recurSubDeviceTagHistory(roleMenus, 500);
        return Wrapper.success();
    }

    /**
     * 获取菜单详情
     *
     * @param request
     * @author wrc
     * @date 2020/7/24
     */
    @Override
    public Wrapper<MiddlegroundMenuUpdateRequest> menuDetails(MenuDetailsRequest request) {
        MiddlegroundMenuUpdateRequest menuDetailsResponse = new MiddlegroundMenuUpdateRequest();
        Optional<MiddlegroundMenu> byId = middlegroundMenuRepository.findById(request.getId());
        if (!byId.isPresent()) {
            return Wrapper.fail(ResponseCode.RECORDS_DON_T_EXIST);
        }
        MiddlegroundMenu middlegroundMenu = byId.get();
        menuDetailsResponse.setId(middlegroundMenu.getId());
        menuDetailsResponse.setMenuDescribe(middlegroundMenu.getMenuDescribe());
        menuDetailsResponse.setUrl(middlegroundMenu.getPath());
        menuDetailsResponse.setParentId(middlegroundMenu.getParentId());
        menuDetailsResponse.setSort(middlegroundMenu.getSort());
        menuDetailsResponse.setMenuName(middlegroundMenu.getMenuName());
        List<MiddlegroundMenu> allByParentIdAndTypeEquals = middlegroundMenuRepository.findAllByParentIdAndTypeEquals(middlegroundMenu.getId(), SystemConstant.MuenType.BUTTON);
        if (null != allByParentIdAndTypeEquals && allByParentIdAndTypeEquals.size() > 0) {
            List<ButtonUpdateRequest> list = new ArrayList<>();
            allByParentIdAndTypeEquals.forEach(menu -> {
                ButtonUpdateRequest buttonUpdateRequest = new ButtonUpdateRequest();
                buttonUpdateRequest.setButtonExplain(menu.getMenuDescribe());
                buttonUpdateRequest.setButtonName(menu.getMenuName());
                buttonUpdateRequest.setButtonUrl(menu.getPath());
                buttonUpdateRequest.setId(menu.getId());
                list.add(buttonUpdateRequest);
            });
            menuDetailsResponse.setButtons(list);
        }
        return Wrapper.success(menuDetailsResponse);
    }

    /**
     * 修改菜单
     *
     * @param request
     * @author wrc
     * @date 2020/7/27
     */
    @Transactional
    @Override
    public Wrapper menuUpdate(MiddlegroundMenuUpdateRequest request) {
        Optional<MiddlegroundMenu> byId = middlegroundMenuRepository.findById(request.getId());
        if (!byId.isPresent()) {
            return Wrapper.fail(ResponseCode.RECORDS_DON_T_EXIST);
        }
        MiddlegroundMenu middlegroundMenu = byId.get();
        middlegroundMenu.setSort(request.getSort());
        middlegroundMenu.setPath(request.getUrl());
        middlegroundMenu.setMenuName(request.getMenuName());
        middlegroundMenu.setMenuDescribe(request.getMenuDescribe());
        middlegroundMenu.setUpdateTime(System.currentTimeMillis());
        middlegroundMenuRepository.save(middlegroundMenu);
        if (null != request && null != request.getButtons() && !request.getButtons().isEmpty()) {
            middlegroundMenuRepository.deleteAllByParentIdEquals(middlegroundMenu.getId());
            List<MiddlegroundMenu> list = new ArrayList<>();
            request.getButtons().forEach(buttonUpdateRequest -> {
                MiddlegroundMenu menu = new MiddlegroundMenu();
                menu.setPath(buttonUpdateRequest.getButtonUrl());
                menu.setMenuName(buttonUpdateRequest.getButtonName());
                menu.setMenuDescribe(buttonUpdateRequest.getButtonExplain());
                menu.setParentId(middlegroundMenu.getId());
                menu.setType(SystemConstant.MuenType.BUTTON);
                menu.setSort(SystemConstant.State.STATE_START);
                menu.setState(SystemConstant.State.STATE_START);
                menu.setCreateTime(System.currentTimeMillis());
                menu.setUpdateTime(System.currentTimeMillis());
                list.add(menu);
            });
            middlegroundMenuRepository.saveAll(list);
        }
        return Wrapper.success();
    }


    /**
     * 分割长List为 subNum/段。
     *
     * @param subNum 每段长度 最小1
     */
    private void recurSubDeviceTagHistory(List<MiddlegroundMenuRole> thesisList, int subNum) {
        if (thesisList.size() > subNum) {
            List<MiddlegroundMenuRole> toInsert = thesisList.subList(0, subNum);
            List<MiddlegroundMenuRole> toRecurSub = thesisList.subList(subNum, thesisList.size());
            roleMenuRepository.saveAll(toInsert);
            recurSubDeviceTagHistory(toRecurSub, subNum);
        } else {
            roleMenuRepository.saveAll(thesisList);
        }
    }


}
